#include "test_list.h"


#ifdef TEST_SFINAE

#include <list>

#include "disable_warning.h"
#include "tools/sfinae.h"

#define TEST_SFINAE_000
#define TEST_SFINAE_001
#define TEST_SFINAE_002
#define TEST_SFINAE_003

#define TEST_SFINAE_004

#define TEST_SFINAE_005
#define TEST_SFINAE_006
#define TEST_SFINAE_007
#define TEST_SFINAE_008
#define TEST_SFINAE_009
#define TEST_SFINAE_010
#define TEST_SFINAE_011
#define TEST_SFINAE_012
#define TEST_SFINAE_013
#define TEST_SFINAE_014
#define TEST_SFINAE_015
#define TEST_SFINAE_016
#define TEST_SFINAE_017
#define TEST_SFINAE_018
#define TEST_SFINAE_019
#define TEST_SFINAE_020
#define TEST_SFINAE_021
#define TEST_SFINAE_022
#define TEST_SFINAE_023
#define TEST_SFINAE_024
#define TEST_SFINAE_025
#define TEST_SFINAE_026
#define TEST_SFINAE_027
#define TEST_SFINAE_028
#define TEST_SFINAE_029
#define TEST_SFINAE_030
#define TEST_SFINAE_031
#define TEST_SFINAE_032

//------------------------------------------------------------------------------------------------------//


namespace{

    DETECTED_MEMBER(fooA);
    DETECTED_MEMBER(fooB);
    DETECTED_MEMBER(v);
    DETECTED_MEMBER(r);
    DETECTED_MEMBER(a);
    DETECTED_MEMBER(p);
    DETECTED_MEMBER(pp);
    DETECTED_MEMBER(private_foo);
//-------------------------------------
    DETECTED_MEMBER(foo);
    DETECTED_MEMBER(val);
    DETECTED_MEMBER(ptr);
    DETECTED_MEMBER(ar);
//-------------------------------------
    DETECTED_MEMBER_BY_NAME(private_fooB);
    DETECTED_MEMBER_BY_NAME(private_foo);
    DETECTED_MEMBER_BY_NAME(onlyconst);
    DETECTED_MEMBER_BY_NAME(noconst);
    DETECTED_MEMBER_BY_NAME(fooA);
    DETECTED_MEMBER_BY_NAME(v);
//-------------------------------------    
    

    int g;
    struct A
    {
        A():r(g){}

        void fooA(int);
        void fooA(int)const;
        void fooA();
        void fooA()const;

        void onlyconst()const;
        void noconst();

        int v;
        int& r;
        int a[10];
        int* p;
        int** pp;
    private:
        void private_foo();
    };

    struct B : A
    {
        int v;
        int fooB(){ return 0; }

        void private_fooB();
    };

    struct Base
    {
        Base():val(g){}
        void foo(float){}
        const char* ptr;
        int& val;
    };

    struct Example:Base
    {
        Example():Base(){}
        using Base::foo;
        void foo()const{}
        int ar[10];
    };

    struct Crol
    {
        void fooA(){}
        void fooA()const{}
        void fooA(float){}
    };
    struct Rabbit : Crol
    {
        int val;
    };

    struct Bar
    {
        Bar(int& g):r(g){}

        void fooA(int);
        void fooA(int)const;
        void fooA();
        void onlyconst()const;
        void noconst();
        int& r;
    private:
        void private_foo();
    };


    struct Der : Bar
    {
        Der(int& g):Bar(g){}
        int fooB(){ return 0; }
    };
    DETECTED_MEMBER(onlyconst);
    DETECTED_MEMBER_BY_NAME(r);

}//namespace
//------------------------------------------------------------------------------------------------------//

#ifdef TEST_SFINAE_000
TEST(tools, sfinae_000)
{
    EXPECT_EQ(true,  is_available(B,int,v)==1 );
    EXPECT_EQ(true,  is_available(B,int&,r)==1 );
    EXPECT_EQ(true,  is_available(B,int[10],a) ==1 );
    EXPECT_EQ(true,  is_available(B,int*,p) ==1 );
    EXPECT_EQ(true,  is_available(B,int**,pp)  ==1 );
}
#endif // TEST_SFINAE_000

#ifdef TEST_SFINAE_001
TEST(tools, sfinae_001)
{
    EXPECT_EQ(true,  is_available(        B,void(int),fooA)  ==1 );
    EXPECT_EQ(true,  is_available_method( B,void(int),fooA)  ==1 );
    EXPECT_EQ(true,  is_available_cmethod(B,void(int),fooA)  ==1 );
    EXPECT_EQ(true,  is_available_method( B,int(),    fooB)  ==1 );
}
#endif // TEST_SFINAE_001

#ifdef TEST_SFINAE_002
#endif // TEST_SFINAE_002

#ifdef TEST_SFINAE_003
TEST(tools, sfinae_003)
{
    EXPECT_EQ(true,  is_available         (Example, void(float), foo)==1 );
    EXPECT_EQ(true,  is_available_method  (Example, void(float), foo)==1 );
    EXPECT_EQ(false, is_available_cmethod (Example, void(float), foo)==1 );

    EXPECT_EQ(true,  is_available        (Example, void(), foo)==1 );
    EXPECT_EQ(false, is_available_method (Example, void(), foo)==1 );
    EXPECT_EQ(true,  is_available_cmethod(Example, void(), foo)==1 );

    EXPECT_EQ(true,  is_available(Example, int[10],      ar)==1  );
    EXPECT_EQ(true,  is_available(Example, int& ,       val)==1 );
    EXPECT_EQ(true,  is_available(Example, const char*, ptr)==1 );
}
#endif // TEST_SFINAE_003

#ifdef TEST_SFINAE_004
TEST(tools, sfinae_004)
{
    EXPECT_EQ(true,  available_data(B,int,   v)==1 );
    EXPECT_EQ(true,  available_data(B,float, v)==0 );

    EXPECT_EQ(true,  can_launch_method(B,void(),     fooA)==1 );
    EXPECT_EQ(true,  can_launch_method(B,void(int),  fooA)==1 );
    EXPECT_EQ(true,  can_launch_method(B,void(void*),fooA)==0 );

    EXPECT_EQ(true,  can_launch_method(B,void(),  onlyconst)==1 );
    EXPECT_EQ(true,  can_launch_cmethod(B,void(), onlyconst)==1 );

    EXPECT_EQ(true,  can_launch_method(B,void(),  noconst)==1 );
    EXPECT_EQ(true,  can_launch_cmethod(B,void(), noconst)==0 );
}
#endif // TEST_SFINAE_004

#ifdef TEST_SFINAE_005
TEST(tools, sfinae_005)
{
    EXPECT_EQ(true,  can_launch_cmethod(Rabbit,void(float), fooA)==0 );
    EXPECT_EQ(true,  can_launch_method( Rabbit,void(float), fooA)==1 );
    
    EXPECT_EQ(true,  is_available(        Rabbit, const int,   val )==0 );
    EXPECT_EQ(true,  is_available(        Rabbit, int,         val )==1 );
    EXPECT_EQ(true,  is_available(        Rabbit, void(float), fooA)==1 );
    EXPECT_EQ(true,  is_available_method( Rabbit, void(float), fooA)==1 );
    EXPECT_EQ(true,  is_available_cmethod(Rabbit, void(float), fooA)==0 );
}
#endif // TEST_SFINAE_005

#ifdef TEST_SFINAE_006
TEST(tools, sfinae_006)
{
    EXPECT_EQ(true,  is_available        ( Der, void(), fooA)==1 );
    EXPECT_EQ(true,  is_available_method ( Der, void(), fooA)==1 );
    EXPECT_EQ(true,  is_available_cmethod( Der, void(), fooA)==0 );
    EXPECT_EQ(true,  is_available        ( Der, void(), onlyconst)==1 );
    EXPECT_EQ(true,  is_available_method ( Der, void(), onlyconst)==0 );
    EXPECT_EQ(true,  is_available_cmethod( Der, void(), onlyconst)==1 );
    EXPECT_EQ(true,  available_data ( Der, void(), onlyconst)==0 );
    EXPECT_EQ(true,  available_data ( Der, int&, r)==1 );
    EXPECT_EQ(true,  can_launch_method ( Der, void(), onlyconst)==1 );
    EXPECT_EQ(true,  can_launch_cmethod( Der, void(), onlyconst)==1 );
}
#endif // TEST_SFINAE_006

#ifdef TEST_SFINAE_007
TEST(tools, sfinae_007)
{
    //EXPECT_EQ(true,  is_available(      B,void(),private_foo)  ==0 );

    EXPECT_EQ(true,  can_launch_method( B,void(),private_fooB)  == 0 );
    EXPECT_EQ(true,  can_launch_method( B,void(),private_foo)   == 0 );
}
#endif // TEST_SFINAE_007

#ifdef TEST_SFINAE_008
#endif // TEST_SFINAE_008

#ifdef TEST_SFINAE_009
#endif // TEST_SFINAE_009

#ifdef TEST_SFINAE_010
#endif // TEST_SFINAE_010

#ifdef TEST_SFINAE_011
#endif // TEST_SFINAE_011

#ifdef TEST_SFINAE_012
#endif // TEST_SFINAE_012

#ifdef TEST_SFINAE_013
#endif // TEST_SFINAE_013

#ifdef TEST_SFINAE_014
#endif // TEST_SFINAE_014

#ifdef TEST_SFINAE_015
#endif // TEST_SFINAE_015

#ifdef TEST_SFINAE_016
#endif // TEST_SFINAE_016

#ifdef TEST_SFINAE_017
#endif // TEST_SFINAE_017

#ifdef TEST_SFINAE_018
#endif // TEST_SFINAE_018

#ifdef TEST_SFINAE_019
#endif // TEST_SFINAE_019

#ifdef TEST_SFINAE_020
#endif // TEST_SFINAE_020

#ifdef TEST_SFINAE_021
#endif // TEST_SFINAE_021

#ifdef TEST_SFINAE_022
#endif // TEST_SFINAE_022

#ifdef TEST_SFINAE_023
#endif // TEST_SFINAE_023

#ifdef TEST_SFINAE_024
#endif // TEST_SFINAE_024

#ifdef TEST_SFINAE_025
#endif // TEST_SFINAE_025

#ifdef TEST_SFINAE_026
#endif // TEST_SFINAE_026

#ifdef TEST_SFINAE_027
#endif // TEST_SFINAE_027

#ifdef TEST_SFINAE_028
#endif // TEST_SFINAE_029

#ifdef TEST_SFINAE_030
#endif // TEST_SFINAE_030

#ifdef TEST_SFINAE_031
#endif // TEST_SFINAE_031

#ifdef TEST_SFINAE_032
#endif // TEST_SFINAE_032

#endif

#include "default_warning.h"

